package com.dankegongyu.lib.http.exception;

import android.net.ParseException;

import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializer;

import org.apache.http.conn.ConnectTimeoutException;
import org.json.JSONException;

import java.io.NotSerializableException;
import java.net.ConnectException;
import java.net.UnknownHostException;

import io.reactivex.annotations.NonNull;
import retrofit2.HttpException;
import retrofit2.Response;

/**
 * @author wpq
 * @version 1.0
 */
public class ApiException extends Exception {

    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;

    public String code;
    public String msg;
    public String data;

    public ApiException() {
    }

    public ApiException(@NonNull Throwable throwable) {
        this(throwable, ERROR.UNKNOWN);
    }

    public ApiException(@NonNull Throwable throwable, int code) {
        this(throwable, "" + code);
    }

    public ApiException(@NonNull Throwable throwable, String code) {
        super(throwable);
        this.code = code;
        this.msg = throwable.getMessage();
    }

    @SuppressWarnings("NullableProblems")
    @Override
    public String toString() {
        return "ApiError{" +
                "code='" + code + '\'' +
                ", msg='" + msg + '\'' +
                ", data='" + data + '\'' +
                '}';
    }

    public static ApiException handleException(Throwable e) {
        ApiException error;
        if (e instanceof HttpException) { // retrofit异常
            HttpException httpException = (HttpException) e;
            error = new ApiException(httpException, httpException.code());
//            switch (httpException.code()) {
//                case UNAUTHORIZED:
//                case FORBIDDEN:
//                case NOT_FOUND:
//                case REQUEST_TIMEOUT:
//                case GATEWAY_TIMEOUT:
//                case INTERNAL_SERVER_ERROR:
//                case BAD_GATEWAY:
//                case SERVICE_UNAVAILABLE:
//                default:
//                    ex.msg = "网络错误";
//                    break;
//            }
            error.msg = httpException.message();
            try {
                Response<?> response = httpException.response();
                if (response != null && response.errorBody() != null) {
                    error.data = response.errorBody().string();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return error;
        } else if (e instanceof ServerException) { // 业务异常
            ServerException serverError = (ServerException) e;
            error = new ApiException(serverError, serverError.errorCode);
            error.msg = serverError.errorMsg;
            error.data = serverError.errorData;
            return error;
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof JsonSerializer
                || e instanceof NotSerializableException
                || e instanceof ParseException) {
            error = new ApiException(e, ERROR.PARSE_ERROR);
            error.msg = "解析错误";
            return error;
        } else if (e instanceof ConnectException) {
            error = new ApiException(e, ERROR.NETWORD_ERROR);
            error.msg = "网络连接错误";
            return error;
        } else if (e instanceof javax.net.ssl.SSLHandshakeException) {
            error = new ApiException(e, ERROR.SSL_ERROR);
            error.msg = "证书验证失败";
            return error;
        } else if (e instanceof ConnectTimeoutException) {
            error = new ApiException(e, ERROR.TIMEOUT_ERROR);
            error.msg = "连接超时";
            return error;
        } else if (e instanceof java.net.SocketTimeoutException) {
            error = new ApiException(e, ERROR.TIMEOUT_ERROR);
            error.msg = "连接超时";
            return error;
        } else if (e instanceof UnknownHostException) {
            error = new ApiException(e, ERROR.UNKNOWNHOST_ERROR);
            error.msg = "域名解析错误";
            return error;
        } else {
            error = new ApiException(e, ERROR.UNKNOWN);
            error.msg = "未知错误";
            return error;
        }
    }

    /**
     * 约定异常
     */
    public static class ERROR {
        /**
         * 未知错误
         */
        public static final String UNKNOWN = "01000";
        /**
         * 解析错误
         */
        public static final String PARSE_ERROR = "01001";
        /**
         * 网络错误
         */
        public static final String NETWORD_ERROR = "01002";
        /**
         * 协议出错
         */
        public static final String HTTP_ERROR = "01003";
        /**
         * 证书出错
         */
        public static final String SSL_ERROR = "01004";
        /**
         * 连接超时
         */
        public static final String TIMEOUT_ERROR = "01005";
        /**
         * 未知主机错误
         */
        public static final String UNKNOWNHOST_ERROR = "01006";
    }
}
